package com.jinke.api.modules.third.sjgj.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.jinke.api.common.api.CommonResult;
import com.jinke.api.common.exception.Asserts;
import com.jinke.api.common.util.CommonUtil;
import com.jinke.api.common.util.EstimateTool;
import com.jinke.api.common.util.Global;
import com.jinke.api.modules.api.conf.ApiUrlsConfig;
import com.jinke.api.modules.app.enums.BalanceLogType;
import com.jinke.api.modules.app.enums.OrderStatus;
import com.jinke.api.modules.app.enums.OrderType;
import com.jinke.api.modules.app.enums.ValidateStatus;
import com.jinke.api.modules.app.model.Order;
import com.jinke.api.modules.app.model.OrderParcel;
import com.jinke.api.modules.app.response.CreateLabel2Response;
import com.jinke.api.modules.app.service.IUserOrderTaskService;
import com.jinke.api.modules.app.service.OrderParcelService;
import com.jinke.api.modules.app.service.OrderService;
import com.jinke.api.modules.app.service.UserRechargeService;
import com.jinke.api.modules.app.util.MathUtil;
import com.jinke.api.modules.app.util.OssUtil;
import com.jinke.api.modules.base.service.ThirdService;
import com.jinke.api.modules.third.ezeeship.model.request.EstimateRateRequest;
import com.jinke.api.modules.third.ezeeship.model.response.CreateLabelResponse;
import com.jinke.api.modules.third.ezeeship.model.response.EstimateRateResponse;
import com.jinke.api.modules.third.ezeeship.util.EzeeShipUtil;
import com.jinke.api.modules.third.sjgj.model.request.GetLabelsRequest;
import com.jinke.api.modules.third.sjgj.model.response.CreateOrderResponse;
import com.jinke.api.modules.third.sjgj.model.response.GetLabelResponse;
import com.jinke.api.modules.third.sjgj.model.response.GetPriceResponse;
import com.jinke.api.modules.third.sjgj.service.SjgjService;
import com.jinke.api.modules.third.sjgj.util.SjgjwlUtil;
import com.jinke.api.modules.ums.model.Channel;
import com.jinke.api.modules.ums.model.UmsAdmin;
import com.jinke.api.modules.ums.service.ChannelService;
import com.jinke.api.modules.ums.service.UmsAdminService;
import com.jinke.api.modules.ums.vo.UserChannelVO;
import com.jinke.api.security.util.ApiUserUtil;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executor;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author macro
 * @since 2024-01-13
 */
@Service
@Slf4j
public class SjgjServiceImpl implements SjgjService {
    @Resource
    private UmsAdminService umsAdminService;
    @Resource
    private Executor createOrderThreadPool;
    @Resource
    private ChannelService channelService;
    @Resource
    private IUserOrderTaskService iUserOrderTaskService;
    @Resource
    private OssUtil ossUtil;
    @Resource
    private SjgjwlUtil sjgjwlUtil;
    @Resource
    private OrderService orderService;
    @Resource
    private ApiUrlsConfig apiUrlsConfig;
    @Resource
    private OrderParcelService orderParcelService;

    @Resource
    private UserRechargeService userRechargeService;
    @Resource
    private ThirdService thirdService;
    @Resource
    private EzeeShipUtil ezeeShipUtil;

    @Override
    public CommonResult estimateRate(EstimateRateRequest request) {
        Integer userId = ApiUserUtil.getUserId();
        return estimateRate(request, userId);
    }

    @Override
    public CommonResult estimateRate(EstimateRateRequest request, Integer userId) {
        UserChannelVO userChannelVO = request.getUserChannelVO();
        Channel channel = userChannelVO.getChannel();
        request.setServiceCode(channel.getChannelCode());
        BigDecimal rateAmount;
        try {
            rateAmount = getPrice(request, userId, userChannelVO, channel.getChannelCode());
        } catch (Exception e) {
            return CommonResult.failed(e.getMessage());
        }
        if (rateAmount.compareTo(new BigDecimal("0")) <= 0) {
            return CommonResult.failed("系统异常，请联系管理人员");
        }
        EstimateRateResponse.Data newData = new EstimateRateResponse.Data();
        newData.setRate(rateAmount);
        return CommonResult.success(newData);

    }


    private BigDecimal getPrice(EstimateRateRequest request, Integer userId, UserChannelVO userChannelVO, String code) {
        BigDecimal priceIfFixPrice = EstimateTool.getPriceIfFixPrice(request);

        BigDecimal rateAmount = new BigDecimal("0");
        BigDecimal originFee = new BigDecimal("50");
        String strResult = sjgjwlUtil.getPrice(request, code);
        if (StringUtils.isNotEmpty(strResult)) {
            GetPriceResponse getPriceResponse = JSONUtil.toBean(strResult, GetPriceResponse.class);
            GetPriceResponse.GetPriceResponseDetail getPriceResponseDetail = getPriceResponse.getResult().get(0);
            if (!getPriceResponse.isSuccess()) {
                throw new RuntimeException(getPriceResponseDetail.getMsg());
            }
            rateAmount = getPriceResponseDetail.getPost_fee()
                    .add(getPriceResponseDetail.getCl_fee())
                    .add(getPriceResponseDetail.getOther_fee())
                    .add(getPriceResponseDetail.getRanyou_fee())
                    .add(getPriceResponseDetail.getGh_fee());
            //成本
            originFee=rateAmount;
            rateAmount = thirdService.calcRate(userId, userChannelVO, rateAmount);
        }

        //如果是9001或9002 直接返回价
        if (priceIfFixPrice!=null){
          //测亏本的  originFee=new BigDecimal("100");
            log.info(request.getOrderNO()+"正常预估"+rateAmount+"转成"+priceIfFixPrice);
            if (priceIfFixPrice.compareTo(originFee)<0){
                //小于成本不让出
                rateAmount=new BigDecimal("0");
            }else {
                //不亏本按固定价
                rateAmount= priceIfFixPrice;
            }
        }
        return rateAmount;
    }

    @Override
    public CommonResult createLabel(EstimateRateRequest request) {
        Integer userId = ApiUserUtil.getUserId();
        return createLabel(request, userId);
    }

    @Override
    public CommonResult createLabel(EstimateRateRequest request, Integer userId) {
        request.setOrderNO(StringUtils.isEmpty(request.getOrderNO()) ? CommonUtil.getOrderNo() : request.getOrderNO());
        Channel channel = channelService.getOne(new LambdaQueryWrapper<Channel>().eq(Channel::getId, request.getChannelId()));
       if (channel.getChannelName().contains("900")){
           String addressLine2 = request.getTo().getAddressLine2();
           String faddressLine2 = request.getFrom().getAddressLine2();

           if (addressLine2==null||addressLine2.equals("null")) {
               request.getTo().setAddressLine2("");
           }
           if (faddressLine2==null||faddressLine2.equals("null")) {
               request.getFrom().setAddressLine2("");
           }
       }


        BigDecimal rateAmount;
        try {
            rateAmount = getPrice(request, userId, request.getUserChannelVO(), channel.getChannelCode());
        } catch (Exception e) {
            return CommonResult.failed(e.getMessage());
        }
        UmsAdmin umsAdmin = umsAdminService.getById(userId);
        if (ObjectUtils.isEmpty(umsAdmin) || rateAmount.compareTo(new BigDecimal("0")) <= 0) {
            return CommonResult.failed("系统异常,请联系管理人员");
        }
        BigDecimal totalAmount = umsAdmin.getCreditBalance().add(umsAdmin.getBalance());
        if (totalAmount.compareTo(rateAmount) < 0) {
            return CommonResult.failed("Insufficient Balance");
        }
        //创建订单
        String strResult = sjgjwlUtil.createOrder(request, channel.getChannelCode());
        if (StringUtils.isNotEmpty(strResult)) {
            CreateOrderResponse createOrderResponse = JSONUtil.toBean(strResult, CreateOrderResponse.class);
            Order order = new Order();
            BeanUtils.copyProperties(request, order);
            order.setId(request.getOrderId());
            long code = createOrderResponse.toCommonResult().getCode();
            if (code==200||code==201) {
                order.setUserId(userId);
                //设置错误信息为空
                order.setErrMsg("");
                order.setOrderNo(request.getOrderNO());
                if (ObjectUtils.isNotEmpty(umsAdmin.getSellerId())) {
                    order.setSellerId(umsAdmin.getSellerId());
                }
                CreateOrderResponse.CreateOrderResponseDetail createOrderResponseDetail = createOrderResponse.getResult().get(0);
                CreateOrderResponse.GetPriceResponseDetail price = createOrderResponseDetail.getPrice();
                BigDecimal afterRate = price.getPost_fee()
                        .add(price.getCl_fee())
                        .add(price.getOther_fee())
                        .add(price.getRanyou_fee())
                        .add(price.getGh_fee()
                        );
                //接口返回的成本价
                order.setOriginFee(afterRate);


                BigDecimal priceIfFixPrice = EstimateTool.getPriceIfFixPrice(request);
                //如果是9001或9002 直接返回价
                if (priceIfFixPrice!=null){
                    log.info(request.getOrderNO()+"正常扣费"+rateAmount+"转成"+priceIfFixPrice);
                    if (priceIfFixPrice.compareTo(afterRate)<0){
                        //小于成本不让出
                        Asserts.fail("当前渠道不可下单");
                    }else {
                        //不亏本按固定价
                        afterRate= priceIfFixPrice;
                    }

                }else {

                    afterRate = thirdService.calcRate(userId, request.getUserChannelVO(), afterRate);
                }



                //真实扣钱也要改
                order.setRate(afterRate);
                // 扣钱
                BigDecimal finalRate = afterRate;
                if (finalRate != null && BigDecimal.ZERO.compareTo(finalRate) < 0) {
                    userRechargeService.decrTransfer(userId, finalRate, BalanceLogType.CONSUME, "寄件", order.getOrderNo(),order.getOrderNo(),channel,null);
                }


                String pdfUrl = createOrderResponseDetail.getLabel_url();
                // 上传到oss
                String objectId = createOrderResponseDetail.getOrderid();
                String newPdfUrl=null;
                if (pdfUrl!=null){
                    ossUtil.upload("pdf", objectId + ".pdf", pdfUrl);
                     newPdfUrl = Global.PRINT_LABEL_API + objectId;
                }
                order.setFromCity(request.getFrom().getCity());
                order.setFromEmail(request.getFrom().getEmail());
                order.setFromCompany(request.getFrom().getCompany());
                order.setFromPhone(request.getFrom().getPhone());
                order.setFromAddressLine2(request.getFrom().getAddressLine2());
                order.setFromAddressLine1(request.getFrom().getAddressLine1());
                order.setFromCountryCode(request.getFrom().getCountryCode());
                order.setFromZipCode(request.getFrom().getZipCode());
                order.setFromPersonName(request.getFrom().getPersonName());
                order.setFromStateCode(request.getFrom().getStateCode());


                try {
                    order.setReference(request.getExtra().getReference());
                    order.setReference2(request.getExtra().getReference2());
                }catch (Exception e){
                    log.error("设置reference出错了");
                }

                EstimateRateRequest.Address requestTo = request.getTo();
                order.setToCity(requestTo.getCity());
                order.setToEmail(requestTo.getEmail());
                order.setToCompany(requestTo.getCompany());
                order.setToPhone(requestTo.getPhone());
                order.setToAddressLine2(requestTo.getAddressLine2());
                order.setToAddressLine1(requestTo.getAddressLine1());
                order.setToCountryCode(requestTo.getCountryCode());
                order.setToZipCode(requestTo.getZipCode());
                order.setToPersonName(requestTo.getPersonName());
                order.setToStateCode(requestTo.getStateCode());
                order.setOrderType(OrderType.API);

                order.setPdfUrl(newPdfUrl);
                order.setStatus(OrderStatus.RECENT.getValue());
                order.setObjectId(objectId);

                order.setCreateTime(LocalDateTime.now());
                if (BooleanUtil.isTrue(requestTo.getIsValid())) {
                    order.setValidateStatus(ValidateStatus.defaultEnum(requestTo.getIsResidential()));
                } else {
                    order.setValidateStatus(ValidateStatus.UN_VALIDATE);
                }
                //保证金比例
                BigDecimal earnestRate = umsAdmin.getEarnestRate();
                BigDecimal subEarnestBalance = MathUtil.formatBigDecimal(afterRate.multiply(earnestRate));
                order.setEarnest(subEarnestBalance);

                orderService.saveOrUpdate(order);
                //定时任务表插入一条数据
                iUserOrderTaskService.saveByOrderId(order.getId());
                //更新包裹信息
                updateParcel(request.getParcels(), userId, order.getId(), createOrderResponseDetail.getTrackingno(),createOrderResponseDetail.getLabel_url());



                return constructResult(createOrderResponseDetail, objectId, newPdfUrl, finalRate);
            } else {
                String message = createOrderResponse.toCommonResult().getMessage().replaceAll("接口返回：：", "");
                message = ezeeShipUtil.fmtMsg(message);
                if (order.getId() != null) {
                    orderService.update(new LambdaUpdateWrapper<Order>().eq(Order::getId, order.getId()).set(Order::getErrMsg, message));
                }
                return CommonResult.failed(message);
            }
        }
        return CommonResult.success();
    }

    /**
     *  更新包裹信息
     * @param parcels
     * @param userId
     * @param orderId
     * @param trackingNo
     * @param labelUrl
     */
    @Transactional
      void updateParcel(List<EstimateRateRequest.Parcel> parcels, Integer userId, Integer orderId,
                        String trackingNo, String labelUrl) {
        // 通过流处理生成新的 orderParcels 并同时设置 trackingNo 和 labelUrl
        List<OrderParcel> orderParcels = parcels.stream().map(parcel -> {
            OrderParcel orderParcel = new OrderParcel();
            orderParcel.setOrderId(orderId);
            orderParcel.setUserId(userId);
            BeanUtils.copyProperties(parcel, orderParcel);

            // 如果 extra 存在，复制其属性
            EstimateRateRequest.Extra extra = parcel.getExtra();
            if (extra != null) {
                BeanUtils.copyProperties(extra, orderParcel);
            }

            // 设置追踪号和标签 URL
            orderParcel.setTrackingNumber(trackingNo);
            orderParcel.setLabelUrl(labelUrl);

            return orderParcel;
        }).collect(Collectors.toList());
        // 先删除再写入
        orderParcelService.remove(new LambdaQueryWrapper<OrderParcel>().eq(OrderParcel::getOrderId, orderId));
        //新增
        orderParcelService.saveBatch(orderParcels);
    }

    @NotNull
    private CommonResult<CreateLabelResponse.Data> constructResult(CreateOrderResponse.CreateOrderResponseDetail createOrderResponseDetail, String objectId,
                                                                   String newPdfUrl, BigDecimal finalRate) {
        CreateLabelResponse.Data result = new CreateLabelResponse.Data();
        result.setRate(finalRate);

        CreateLabel2Response.FeeDetail newFeeDetail = new CreateLabel2Response.FeeDetail();
        newFeeDetail.setBaseRate(finalRate);
        result.setFeeDetail(newFeeDetail);

        result.setRate(finalRate);
        result.setStatus(1);
        result.setCreateTime(LocalDateTime.now());
        result.setObjectId(objectId);
        result.setPdfUrl(newPdfUrl);
        result.setTrackingNumber(Arrays.asList(createOrderResponseDetail.getTrackingno()));
        String uri = Global.PRINT_LABEL_API;
        result.setLabelUrl(Arrays.asList(uri + objectId));

        return CommonResult.success(result);
    }

    @Override
    public CommonResult getLabel(String objectId) {

        return getLabel(objectId, null);

    }

    @Override
    public CommonResult getLabel(String objectId, Integer userId) {
        log.info("sjgj获取面单"+JSONUtil.toJsonStr(objectId));

        CreateLabelResponse.Data createLabelResponseData = new CreateLabelResponse.Data();

        if (userId == null) {
            userId = ApiUserUtil.getUserId();
        }
        Order order = orderService.getOne(new LambdaQueryWrapper<Order>()
                .and(wp -> {
                    wp.eq(Order::getPlatformNo,  objectId)
                            .or().eq(Order::getOrderNo,  objectId)
                            .or().eq(Order::getObjectId,  objectId)
                    ;
                })
                .eq(Order::getUserId, userId)
        );

        if (order == null) {
            return CommonResult.success(createLabelResponseData);
        }

        CreateLabelResponse.Data result = new CreateLabelResponse.Data();
        result.setObjectId(objectId);
        //三方的ID 即平台no
        result.setOrderid(order.getPlatformNo());



        //查询包裹
        List<OrderParcel> parcels = orderParcelService.lambdaQuery()
                .eq(OrderParcel::getOrderId, order.getId())
                .isNull(OrderParcel::getDeletedAt)
                .list();
        List<String> collect = parcels.stream().map(OrderParcel::getTrackingNumber).collect(Collectors.toList());
        result.setTrackingNumber(collect);
        result.setPdfUrl(order.getPdfUrl());
        BigDecimal finalRate = order.getRate();
        result.setRate(finalRate);
        result.setStatus(createLabelResponseData.getStatus());
        CreateLabel2Response.FeeDetail newFeeDetail = new CreateLabel2Response.FeeDetail();
        newFeeDetail.setBaseRate(finalRate);
        result.setFeeDetail(newFeeDetail);

        result.setCreateTime(createLabelResponseData.getCreateTime());

        String labelUrl = Global.PRINT_LABEL_API + objectId;
        result.setLabelUrl(Arrays.asList(labelUrl));
        return CommonResult.success(result);

    }


    /**
     * 查延迟单面单
     * @param platformNo
     * @return
     */
    public CommonResult getLabelfoys(List<String> platformNo ) {
        List<CreateLabelResponse.Data> relist = new ArrayList<>()  ;
        List<GetLabelResponse.CreateOrderResponseDetail> badrelist = new ArrayList<>()  ;

        GetLabelsRequest req=new GetLabelsRequest();
        req.setOrderids(platformNo);
        //查询结果
        String labels = sjgjwlUtil.getLabels(req);
        if (StringUtils.isNotEmpty(labels)) {

            Gson gson = new Gson();
            Type listType = new TypeToken<List<GetLabelResponse.CreateOrderResponseDetail>>(){}.getType();
            List<GetLabelResponse.CreateOrderResponseDetail> getLabelResponse = gson.fromJson(labels, listType);
            CreateLabelResponse.Data newCreateLabelResponseData=null;
            for (GetLabelResponse.CreateOrderResponseDetail temp : getLabelResponse) {
                if (temp.getCode()==200){
                     newCreateLabelResponseData = new CreateLabelResponse.Data();
                    String label_url = temp.getLabel_url();
                    String trackingno = temp.getTrackingno();
                    List<String> trList=new ArrayList<>();
                    trList.add(trackingno);
                    newCreateLabelResponseData.setOrderid(temp.getOrderid());
                    newCreateLabelResponseData.setTrackingNumber(trList);
                    newCreateLabelResponseData.setLabelUrl(Arrays.asList(label_url));
                    relist.add(newCreateLabelResponseData);

                }else {
                    badrelist.add(temp );

                }


            }

            log.error("延迟没返回的"+new Gson().toJson(badrelist));

//            String labelUrl = apiUrlsConfig.getDomain() + "/api/shipment/printLabel?platformNo=" + platformNo;
        }
        return CommonResult.success(relist);

    }



    /**
     * 获取面单并更新
     *
     * @param platformNo2orderIdMap
     * @param batchPlatformIds
     */
    @Override
    public  void getLabelAndUpdate(Map<String, Integer> platformNo2orderIdMap, List<String> batchPlatformIds) {
        //开启多线程
        createOrderThreadPool.execute(() -> {
            //走接口获取面单信息
            CommonResult label = getLabelfoys(batchPlatformIds);
            List<CreateLabelResponse.Data> reList = (List<CreateLabelResponse.Data>) label.getData();
            for (CreateLabelResponse.Data data : reList) {

                List<String> trackingNumber = data.getTrackingNumber();
                List<String> trackingUrl = data.getTrackingUrl();
                List<String> labelUrls = data.getLabelUrl();

                if (CollectionUtil.isNotEmpty(labelUrls)) {
                    //对应的订单号
                    Integer orderId = platformNo2orderIdMap.get(data.getOrderid());
                    //查询包裹
                    List<OrderParcel> parcels = orderParcelService.lambdaQuery()
                            .eq(OrderParcel::getOrderId, orderId)
                            .isNull(OrderParcel::getDeletedAt)
                            .list();
                    String mainPdfUrl = labelUrls.get(0);
                    for (int j = 0; j < parcels.size(); j++) {
                        OrderParcel orderParcel = parcels.get(j);
                        if (trackingNumber != null) {
                            orderParcel.setTrackingNumber(trackingNumber.get(j));
                        }
                        if (trackingUrl != null) {
                            orderParcel.setTrackingUrl(trackingUrl.get(j));
                        }
                        String tmpName = CommonUtil.getOrderNo();
                        try {
                            String pdf = ossUtil.uploadforYCD("pdf", tmpName + ".pdf", labelUrls.get(j));
                            if (StringUtils.isBlank(pdf)) {
                                //上传失败
                                orderParcel.setLabelUrl(mainPdfUrl);

                            } else {
                                //上传成功
                                String newLabelUrl = apiUrlsConfig.getDomain() + "/api/label/printLabel?objectId=" + tmpName;
                                if (j == 0) {
                                    //取第一个为新面单
                                    mainPdfUrl = newLabelUrl;
                                }
                                orderParcel.setLabelUrl(newLabelUrl);
                            }
                        } catch (Exception e) {
                            orderParcel.setLabelUrl(mainPdfUrl);
                            log.error("延迟单面单上传出错orderId-" + orderId);
                        }

                    }
                    //更新包裹
                    orderParcelService.updateBatchById(parcels);

                    LambdaUpdateWrapper<Order> updateWrapper = new LambdaUpdateWrapper<Order>()
                            .eq(Order::getId, orderId)
                            .set(Order::getPdfUrl, mainPdfUrl);
                    //更新订单pdfurl
                    orderService.update(updateWrapper);
                    log.error("延迟单更新成功" + data);
                } else {
                    log.error("延迟单暂时没获取到" + data);
                }
            }


        });
    }


    @Override
    public CommonResult cancelLabel(String objectId,String orderNo) {
        String strResult = sjgjwlUtil.cancelLabel(objectId,orderNo);
        if (StringUtils.isNotBlank(strResult)) {
            CreateOrderResponse createLabelResponse = JSONUtil.toBean(strResult, CreateOrderResponse.class);
            List<CreateOrderResponse.CreateOrderResponseDetail> result = createLabelResponse.getResult();
            if (CollectionUtil.isNotEmpty(result)) {
                if (result.get(0).getCode() != 300) {
                    return CommonResult.failed(result.get(0).getMsg());
                }
            }
        }
        return CommonResult.success();
    }

    @Override
    public CommonResult tracking(String trackingNumber) {
        String strResult = sjgjwlUtil.tracking(trackingNumber);
        if (StringUtils.isNotBlank(strResult)) {
            CreateOrderResponse createLabelResponse = JSONUtil.toBean(strResult, CreateOrderResponse.class);
            List<CreateOrderResponse.CreateOrderResponseDetail> result = createLabelResponse.getResult();
            if (CollectionUtil.isNotEmpty(result)) {
                if (result.get(0).getCode() != 300) {
                    return CommonResult.failed(result.get(0).getMsg());
                }
            }

        }
        return CommonResult.success();
    }

    @Override
    public CommonResult cancelInsurance(String insuranceId) {

        return CommonResult.success();
    }
}
